Skip to content

Support Gradle to 9.4, AGP 9.1, Kotlin 2.3, Java 26#56222

Draft
leotm wants to merge 1 commit intofacebook:mainfrom
leotm:gradle-9.4
Draft

Support Gradle to 9.4, AGP 9.1, Kotlin 2.3, Java 26#56222
leotm wants to merge 1 commit intofacebook:mainfrom
leotm:gradle-9.4

Conversation

@leotm
Copy link
Copy Markdown
Contributor

@leotm leotm commented Mar 25, 2026

Summary:

Follow-up to

  • bump Gradle wrappers from 9.3.1 to 9.4.1 (root, RNGP, helloworld)
    • Java 26 support
  • bump RNGP: AGP from 8.12.0 to 9.1.0, Kotlin from 2.1.20 to 2.3.0 (RNGP)
  • bump RNGP Kotlin compiler API ver from KOTLIN_1_8 to KOTLIN_2_3 (RNGP)
    • or preserve lower API ver as before
  • AGP 9 DSL syntax updates
    • NB: AGP 9.1 removed direct prop accessors, replaced by lambdas (DSL closures)
    • React Plugin .kt
      • fix: arg type mismatch: actual type is File, String expected
      • old .asFile returns File, directories.add() needs String, use .asFile.absolutePath to convert File to String path
      • NB: AGP 9 replaced .srcDir with directories.add, expects String paths (not File objs)
    • AGP config utils .kt
      • fix: unresolved ref 'namespace' - update to lambdas
      • fix: NoSuchMethodError for buildFeatures, 'LibraryBuildFeatures LibraryExtension.getBuildFeatures()' - update to lambdas
    • NDK config utils .kt
      • fix: com.android.build.api.dsl. ApplicationBuildFeatures ApplicationExtension.getBuildFeatures breaking rn-tester createBundleReleaseJsAndAssets - update to lambdas
      • fix: com.android.build.api.dsl. ApplicationDefaultConfig ApplicationExtension.getDefaultConfig() breaking rn-tester createBundleReleaseJsAndAssets - update to lambdas
    • ReactAndroid build.gradle .kts
      • fix: java.exclude Unresolved ref 2 script compilation errors - refactor legacy Java source exclusion to explicit filter patterns (Ant-style globs)
      • NB: AGP 9 AndroidSourceDirectorySet stopped extending PatternFilterable
  • JSON Utils tests .kt
    • fix: :gradle-plugin:shared:compileTestKotlin 40 warnings as errors Unnecessary non-null assertion (!!) on a non-null receiver - assert null once at entry point of vars
  • /helloworld
    • fix: Failed to apply plugin 'org.jetbrains.kotlin.android' in :app no longer required for Kotlin support since AGP 9 - remove from app/build.gradle
    • NB: remaining 'org.jetbrains.kotlin.android' refs can be fully removed from codebase after, keeping this PR scope minimal
    • NB: this is required in @react-native-community/template first, for test_e2e_android_templateapp debug/release (init-project-e2e.js RNTestProject) to pass final CI checks
  • /react-native-fantom (TODO, new error)
    • build script
      • fix: Failed to apply plugin 'com.facebook.react' too late to call finalizeDsl as the DSL finalization blocks have already been executed. In particular, you cannot call finalizeDsl within the beforeVariants or onVariants blocks. Instead, you must call finalizeDsl directly within the androidComponents block

TODO

  • gradle/wrapper/gradle-wrapper.jar
  • packages/gradle-plugin/gradle/wrapper/gradle-wrapper.jar
  • packages/gradle-plugin/gradlew
  • packages/gradle-plugin/gradlew.bat
  • private/helloworld/android/gradle/wrapper/gradle-wrapper.jar
  • private/helloworld/android/gradlew
  • private/helloworld/android/gradlew.bat
  • gradlew
  • gradlew.bat

NB: official Gradle 9.4 support in Kotlin 2.4.0-Beta2 (April 22, 2026)

TODO: split into incremental atomic PRs to accomplish Java 26 build time support

Changelog:

[ANDROID] [CHANGED] - Upgradle to Gradle 9.4, Kotlin 2.3, AGP 9.1 and support Java 26

Test Plan:

  • local machine: win11, CMake: 3.30.5, 4.3.1, JDK 17 (JDK 26 incompat sec)
  • locally run Android GHA yml workflows
    • nightly problematic, use prebuilt stable com.facebook.hermes:hermes-android:0.16.0 artifact
      • mvnrepository.com/artifact/com.facebook.hermes/hermes-android/0.16.0
    • useHermesStable=true, useHermesNightly=false, hermesV1Enabled=false, .hermesversion, version.properties
    • set: ANDROID_SDK_ROOT, JAVA_HOME, NODE_HOME (prepend all to PATH)
    • flags: -PreactNativeArchitectures=arm64-v8a -PenableWarningsAsErrors=true --no-daemon
  • .\gradlew .\gradlew :private:react-native-fantom:buildFantomTester locally on 0.16.0 tarball 404
    • .github\actions\build-fantom-runner\action.yml locally requires private:react-native-fantom and compiling hermes from source w debug flags (SLOW af)
  • .\gradlew :packages:react-native:ReactAndroid:tasks
  • .\gradlew :packages:react-native:ReactAndroid:build --dry-run
  • .\gradlew :packages:react-native:ReactAndroid:buildCodegenCLI
    • fix locally for Windows Git Bash compat
  • .\gradlew :gradle-plugin:react-native-gradle-plugin:compileKotlin
  • .\gradlew :packages:rn-tester:android:app:createBundleReleaseJsAndAssets
  • .\gradlew :packages:react-native:ReactAndroid:buildCMakeRelease[arm64-v8a][hermestooling,jsi,etc]
  • :packages:react-native:ReactAndroid:testDebugUnitTest 420ish tests
  • :packages:react-native:ReactAndroid:testReleaseUnitTest less tests
  • .\gradlew :packages:react-native:ReactAndroid:build (the beast)
    • 14m 17s clean build 1 arch
    • 1m 28s cached build 1 arch
  • react-native-community/template: .\gradlew app:assembleRelease

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Mar 25, 2026
@leotm leotm force-pushed the gradle-9.4 branch 4 times, most recently from 58dc716 to eada3f9 Compare March 31, 2026 20:25
@usta
Copy link
Copy Markdown

usta commented Apr 1, 2026

Gradle 9.4.0 -> 9.4.1

Also agp 9.2 require at least 9.5.x so if this is not so urget it can wait until 9.5.x series became stable ( Right now it is https://github.com/gradle/gradle/releases/tag/v9.5.0-RC1 )

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 4, 2026

Warning

JavaScript API change detected

This PR commits an update to ReactNativeApi.d.ts, indicating a change to React Native's public JavaScript API.

  • Please include a clear changelog message.
  • This change will be subject to additional review.

This change was flagged as: POTENTIALLY_BREAKING

@leotm leotm force-pushed the gradle-9.4 branch 3 times, most recently from 9a017c2 to 53c90d6 Compare April 8, 2026 18:38
@leotm leotm changed the title Bump Gradle to 9.4 (Kotlin to 2.3, AGP to 9.1) Upgrade Gradle to 9.4 (Kotlin to 2.3, AGP to 9.1) Apr 8, 2026
@leotm leotm changed the title Upgrade Gradle to 9.4 (Kotlin to 2.3, AGP to 9.1) Upgrade Gradle to 9.4 (Kotlin 2.3, AGP 9.1. JDK 26) Apr 8, 2026
@leotm leotm changed the title Upgrade Gradle to 9.4 (Kotlin 2.3, AGP 9.1. JDK 26) Upgrade Gradle to 9.4 (Kotlin 2.3, AGP 9.1, JDK 26) Apr 8, 2026
@leotm leotm changed the title Upgrade Gradle to 9.4 (Kotlin 2.3, AGP 9.1, JDK 26) Support Gradle to 9.4, AGP 9.1, Kotlin 2.3, Java 26 Apr 14, 2026
@usta
Copy link
Copy Markdown

usta commented Apr 16, 2026

It looks like this is just a AI hallucination PR KotlinVersion.KOTLIN_2_3 doesn't even supported in grade 9.4.1 also seen some parts just added like try to fix without logic. Meta should put a STRICT forbidding rules for any kind of AI agent helped PRs .
Source : https://docs.gradle.org/9.4.1/userguide/compatibility.html

@leotm
Copy link
Copy Markdown
Contributor Author

leotm commented Apr 25, 2026

NB: CI errors resolved via re-runs

lint

https://github.com/facebook/react-native/actions/runs/24193792111/job/70617965386

[5/5] Building fresh packages...
error /home/runner/work/react-native/react-native/node_modules/electron: Command failed.
info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.
Exit code: 1
Command: node install.js
Arguments: 
Directory: /home/runner/work/react-native/react-native/node_modules/electron
Output:
HTTPError: Response code 403 (Forbidden)
    at Request._onResponseBase (/home/runner/work/react-native/react-native/node_modules/got/dist/source/core/index.js:913:31)
    at Request._onResponse (/home/runner/work/react-native/react-native/node_modules/got/dist/source/core/index.js:948:24)
    at ClientRequest.<anonymous> (/home/runner/work/react-native/react-native/node_modules/got/dist/source/core/index.js:962:23)
    at Object.onceWrapper (node:events:639:26)
    at ClientRequest.emit (node:events:536:35)
    at origin.emit (/home/runner/work/react-native/react-native/node_modules/@szmarczak/http-timer/dist/source/index.js:43:20)
    at HTTPParser.parserOnIncomingClient (node:_http_client:702:27)
    at HTTPParser.parserOnHeadersComplete (node:_http_common:118:17)
    at TLSSocket.socketOnData (node:_http_client:544:22)
    at TLSSocket.emit (node:events:524:28)
error Command failed.
Exit code: 1
test_e2e_android_rntester (release)

https://github.com/facebook/react-native/actions/runs/24410144484/job/71309405314

Failed to install apk /tmp/maestro-app1567499255242633231.apk: Install failed: 

The stack trace was:
java.io.IOException: Failed to install apk /tmp/maestro-app1567499255242633231.apk: Install failed: 
	at maestro.drivers.AndroidDriver.install(AndroidDriver.kt:1166)
	at maestro.drivers.AndroidDriver.access$install(AndroidDriver.kt:64)
	at maestro.drivers.AndroidDriver$installMaestroDriverApp$1.invoke(AndroidDriver.kt:1090)
	at maestro.drivers.AndroidDriver$installMaestroDriverApp$1.invoke(AndroidDriver.kt:1079)
	at maestro.utils.Metrics.measured(Metrics.kt:48)
	at maestro.drivers.AndroidDriver.installMaestroDriverApp(AndroidDriver.kt:1079)
	at maestro.drivers.AndroidDriver.installMaestroApks(AndroidDriver.kt:1117)
	at maestro.drivers.AndroidDriver.open(AndroidDriver.kt:97)
	at maestro.Maestro$Companion.android(Maestro.kt:636)
	at maestro.cli.session.MaestroSessionManager.createAndroid(MaestroSessionManager.kt:283)
	at maestro.cli.session.MaestroSessionManager.createMaestro(MaestroSessionManager.kt:165)
	at maestro.cli.session.MaestroSessionManager.newSession(MaestroSessionManager.kt:88)
	at maestro.cli.session.MaestroSessionManager.newSession$default(MaestroSessionManager.kt:54)
	at maestro.cli.command.TestCommand.runShardSuite(TestCommand.kt:333)
	at maestro.cli.command.TestCommand.access$runShardSuite(TestCommand.kt:65)
	at maestro.cli.command.TestCommand$handleSessions$1$results$1$1.invokeSuspend(TestCommand.kt:300)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:111)
	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:99)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:585)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:802)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:706)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:693)
Caused by: java.io.IOException: Install failed: 
	at dadb.Dadb$DefaultImpls.install(Dadb.kt:94)
	at dadb.adbserver.AdbServerDadb.install(AdbServer.kt:122)
	at dadb.Dadb$DefaultImpls.install(Dadb.kt:80)
	at dadb.adbserver.AdbServerDadb.install(AdbServer.kt:122)
	at maestro.drivers.AndroidDriver.install(AndroidDriver.kt:1164)
	... 23 more
run_fantom_tests failed

https://github.com/facebook/react-native/actions/runs/24410228534/job/71306995339

Summary of all failing tests
FAIL packages/react-native/Libraries/ReactNative/__tests__/State-ForcedCloneCommitHook-itest.js
  ● Test suite failed to run

    Command failed (status code: (empty), signal: SIGSEGV): /__w/react-native/react-native/private/react-native-fantom/build/tester/fantom_tester --bundlePath /__w/react-native/react-native/private/react-native-fantom/.out/js-builds/run-1776184371910/1776184451876-State-ForcedCloneCommitHook-itest.js.bundle.js --featureFlags {"updateRuntimeShadowNodeReferencesOnCommit":false} --minLogLevel error

    stdout:
    (empty)

    stderr:
    (empty)

      155 |
      156 |   if (result.status !== 0) {
    > 157 |     throw new Error(getDebugInfoFromCommandResult(getResultWithOutput()));
          |           ^
      158 |   }
      159 |
      160 |   if (EnvironmentOptions.printCLIOutput) {

      at processRNTesterCommandResult (private/react-native-fantom/runner/runner.js:157:11)
      at runTest (private/react-native-fantom/runner/runner.js:423:5)


Test Suites: 1 failed, 20 skipped, 78 passed, 79 of 99 total

@leotm
Copy link
Copy Markdown
Contributor Author

leotm commented Apr 25, 2026

thanks for the comments @usta

It looks like this is just a AI hallucination PR KotlinVersion.KOTLIN_2_3 doesn't even supported in grade 9.4.1
Source : https://docs.gradle.org/9.4.1/userguide/compatibility.html

this is factually incorrect

by this logic, main branch - Gradle 9.3.1, KGP 2.1.20, apiVersion KOTLIN_1_8, AGP 8.12.0
#50780 #52973 #55453 are unsupported hallucination PRs
Kotlin 2.1.20 is fully compat with Gradle 7.6.3-8.11, not 9.3.1
latest Gradle releases actually can be used, which we're doing on main

the Gradle compat matrix says nothing about KotlinVersion constants derived from KGP source code

KotlinVersion.KOTLIN_2_3 exists
KOTLIN_1_8 is a hard compiler error, deprecated from documention
KotlinVersion.KOTLIN_2_3 is the default, it makes zero difference

the compat matrix states Gradle 9.4.1 embeds Kotlin 2.3.0 compiler that evals build.gradle.kts files on 2.2 syntax
none of the RNGP build scripts in the 4 submodules use 2.3 syntax

"Gradle is tested with Kotlin 2.0.0 through 2.3.20-Beta1" shows KGP 2.3 can compile .kt source files

RNGP's bundled KGP apiVersion KOTLIN_2_3 value is a binary compat marker encoded in bytecode when the JAR gets compiled, it has nothing to do with Gradle's Kotlin defaults

seen some parts just added like try to fix without logic

no, each DSL migration is a trivial documented AGP 9+ change

Also agp 9.2 require at least 9.5.x so if this is not so urget it can wait until 9.5.x series became stable ( Right now it is https://github.com/gradle/gradle/releases/tag/v9.5.0-RC1 )

AGP 9.2 defaults to minimum Gradle is 9.4.1, not 9.5.x

Gradle 9.4.0 -> 9.4.1 [Apr 1]
~~ Kotlin 2.3.0 -> 2.3.20 ~~ edited(deleted) Apr 16

editing this out then claiming KOTLIN_2_3 isn't supported, I don't follow the reasoning

Meta should put a STRICT forbidding rules for any kind of AI agent helped PRs

you've been subscribed to the PR, iterated on over a month, each Android CI failure fixed incrementally
if you actually have technical concerns about specific changes, happy to address

@leotm leotm force-pushed the gradle-9.4 branch 2 times, most recently from d430adf to 5d090b8 Compare April 25, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants